﻿#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>

//struct stu//创建一个结构体类型 学生
//{
//	char name[20];
//	int age[5];
//};
//
//int cmp_stu_by_age(const void* e1, const void* e2)
//{
//	return ((struct stu*)e1)->age - ((struct stu*)e2)->age;
//}
//
//int main()
//{
//	//创建一个结构体变量并且初始化
//	struct stu s[] = {{"zhangsan",20},{"lisi",30},{"wangwu",15}};
//	int sz = sizeof(s) / sizeof(s[0]);
//	qsort(s, sz, sizeof(s[0]), cmp_stu_by_age);
//	return 0;
//}


//struct Stu //学⽣
//{
//	char name[20];//名字
//	int age;//年龄
//};
////假设按照年龄来⽐较
//int cmp_stu_by_age(const void* e1, const void* e2)
//{
//	return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
//}
////strcmp - 是库函数，是专⻔⽤来⽐较两个字符串的⼤⼩的
////假设按照名字来⽐较
//int cmp_stu_by_name(const void* e1, const void* e2)
//{
//	return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
//}
////按照年龄来排序
//void test2()
//{
//	struct Stu s[] = { {"zhangsan", 20}, {"lisi", 30}, {"wangwu", 15} };
//	int sz = sizeof(s) / sizeof(s[0]);
//	qsort(s, sz, sizeof(s[0]), cmp_stu_by_age);
//}
////按照名字来排序
//void test3()
//{
//	struct Stu s[] = { {"zhangsan", 20}, {"lisi", 30}, {"wangwu", 15} };
//	int sz = sizeof(s) / sizeof(s[0]);
//	qsort(s, sz, sizeof(s[0]), cmp_stu_by_name);
//}
//int main()
//{
//	test2();
//	//test3();
//	return 0;
//}


//#include <stdio.h>
//int main()
//{
//	int a[3][4] = { 0 };
//	//sizeof(数组名)，这是单独的数组名，表示整个数组
//	printf("%zd\n", sizeof(a));//48 = 3*4*4
//	//a[0][0]就是二维数组的第一行第一列的元素
//	printf("%zd\n", sizeof(a[0][0]));//4
//	//在学习二维数组的时候，我们是把每一行看成一个一维数组，
//	//那些一维数组就是二维数组的元素，而a[0]就是第一行的一维数组
//	//然后就会发现整个a[0]是那个一维数组的数组名，sizeof(数组名)
//	printf("%zd\n", sizeof(a[0]));//16 = 4*4
//	//sizeof(数组名+1),这个数组名就表示首元素的地址，再+1，就是第二个元素的地址&a[0][1]
//	printf("%zd\n", sizeof(a[0] + 1));// 4/8
//	//* &a[0][1]<-->a[0][1]
//	printf("%zd\n", sizeof(*(a[0] + 1)));//4
//	//a这里是二维数组的数组名，表示的是首元素的地址，而二维数组的元素是一维数组
//	//a<-->&a[0]，再+1，就是&a[1]
//	printf("%zd\n", sizeof(a + 1));// 4/8
//	//* &a[1]<-->a[1]，这是第二行的一维数组的数组名
//	printf("%zd\n", sizeof(*(a + 1)));//16 = 4*4
//	//a[0]是数组名，&a[0]，拿到的是第一行的一维数组的地址，再+1，就是第二行的地址
//	printf("%zd\n", sizeof(&a[0] + 1));// 4/8
//	//根据上面就可以知道整个解引用之后拿到的是第二行的所有元素
//	printf("%zd\n", sizeof(*(&a[0] + 1)));//16 = 4*4
//	//这里的a是首元素的地址，也就是第一行的地址，解引用之后就拿到了第一行所有元素
//	printf("%zd\n", sizeof(*a));//16 = 4*4
//	//虽然这个已经越界访问了，但是还是可以拿到第四行的所有元素
//	printf("%zd\n", sizeof(a[3]));//16 = 4*4
//	return 0;
//}


//#include <stdio.h>
//int main()
//{
//	int a[5] = { 1, 2, 3, 4, 5 };
//	int* ptr = (int*)(&a + 1);
//	printf("%d,%d", *(a + 1), *(ptr - 1));
//	return 0;
//}


////在X86环境下
////假设结构体的⼤⼩是20个字节
//struct Test
//{
//	int Num;
//	char* pcName;
//	short sDate;
//	char cha[2];
//	short sBa[4];
//}*p = (struct Test*)0x100000;
//
//int main()
//{
//	printf("%p\n", p + 0x1);
//	printf("%p\n", (unsigned long)p + 0x1);
//	printf("%p\n", (unsigned int*)p + 0x1);
//	return 0;
//}


//#include <stdio.h>
//int main()
//{
//	int a[3][2] = { (0, 1), (2, 3), (4, 5) };
//	int* p;
//	p = a[0];
//	printf("%d", p[0]);
//	return 0;
//}


////在x86环境下
//#include <stdio.h>
//int main()
//{
//	int a[5][5];
//	int(*p)[4];
//	p = a;
//	printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
//	return 0;
//}


//#include <stdio.h>
//int main()
//{
//	int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
//	int* ptr1 = (int*)(&aa + 1);
//	int* ptr2 = (int*)(*(aa + 1));
//	printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));
//	return 0;
//}


//#include <stdio.h>
//int main()
//{
//	char* a[] = { "work","at","alibaba" };
//	char** pa = a;
//	pa++;
//	printf("%s\n", *pa);
//	return 0;
//}


//#include <stdio.h>
//int main()
//{
//	char* c[] = { "ENTER","NEW","POINT","FIRST" };
//	char** cp[] = { c + 3,c + 2,c + 1,c };
//	char*** cpp = cp;
//	printf("%s\n", **++cpp);
//	printf("%s\n", *-- * ++cpp + 3);
//	printf("%s\n", *cpp[-2] + 3);
//	printf("%s\n", cpp[-1][-1] + 1);
//	return 0;
//}